home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / grafik / gif386 / gifload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-13  |  15.4 KB  |  528 lines

  1. /*
  2.  * xgifload.c  -  based strongly on...
  3.  *
  4.  * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
  5.  *
  6.  * Copyright (c) 1988, 1989 by Patrick J. Naughton
  7.  *
  8.  * Author: Patrick J. Naughton
  9.  * naughton@wind.sun.com
  10.  *
  11.  * Permission to use, copy, modify, and distribute this software and its
  12.  * documentation for any purpose and without fee is hereby granted,
  13.  * provided that the above copyright notice appear in all copies and that
  14.  * both that copyright notice and this permission notice appear in
  15.  * supporting documentation.
  16.  *
  17.  * This file is provided AS IS with no warranties of any kind.  The author
  18.  * shall have no liability with respect to the infringement of copyrights,
  19.  * trade secrets or any patents by this file or any part thereof.  In no
  20.  * event will the author be liable for any lost revenue or profits or
  21.  * other special, indirect and consequential damages.
  22.  *
  23.  */
  24.  
  25. #include "gif386.h"
  26.  
  27. typedef int boolean;
  28.  
  29. #define NEXTBYTE (*ptr++)
  30. #define IMAGESEP 0x2c
  31. #define INTERLACEMASK 0x40
  32. #define COLORMAPMASK 0x80
  33.  
  34. FILE *fp;
  35.  
  36. int BitOffset = 0,        /* Bit Offset of next code */
  37.     XC = 0, YC = 0,        /* Output X and Y coords of current pixel */
  38.     Pass = 0,            /* Used by output routine if interlaced pic */
  39.     OutCount = 0,        /* Decompressor output 'stack count' */
  40.     RWidth, RHeight,        /* screen dimensions */
  41.     Width, Height,        /* image dimensions */
  42.     LeftOfs, TopOfs,        /* image offset */
  43.     BitsPerPixel,        /* Bits per pixel, read from GIF header */
  44.     BytesPerScanline,        /* bytes per scanline in output raster */
  45.     ColorMapSize,        /* number of colors */
  46.     Background,            /* background color */
  47.     CodeSize,            /* Code size, read from GIF header */
  48.     InitCodeSize,        /* Starting code size, used during Clear */
  49.     Code,            /* Value returned by ReadCode */
  50.     MaxCode,            /* limiting value for current code size */
  51.     ClearCode,            /* GIF clear code */
  52.     EOFCode,            /* GIF end-of-information code */
  53.     CurCode, OldCode, InCode,    /* Decompressor variables */
  54.     FirstFree,            /* First free code, generated per GIF spec */
  55.     FreeCode,            /* Decompressor, next free slot in hash table */
  56.     FinChar,            /* Decompressor variable */
  57.     BitMask,            /* AND mask for data size */
  58.     ReadMask;            /* Code AND mask for current code size */
  59.     
  60. boolean Interlace, HasColormap;
  61. boolean Verbose = False;
  62.  
  63. byte *Image;            /* The result array */
  64. byte *RawGIF;            /* The heap array to hold it, raw */
  65. byte *Raster;            /* The raster data stream, unblocked */
  66.  
  67.     /* The hash table used by the decompressor */
  68. int Prefix[4096];
  69. int Suffix[4096];
  70.  
  71.     /* An output array used by the decompressor */
  72. int OutCode[1025];
  73.  
  74.     /* The color map, read from the GIF header */
  75. byte Red[256], Green[256], Blue[256], used[256];
  76. int  numused;
  77.  
  78. char *id = "GIF87a";
  79.  
  80.  
  81.  
  82. /*****************************/
  83. LoadGIF(fname)
  84.   char *fname;
  85. /*****************************/
  86. {
  87.     int            filesize;
  88.     register byte  ch, ch1;
  89.     register byte *ptr, *ptr1;
  90.     register int   i;
  91.  
  92.     if (strcmp(fname,"-")==0) { fp = stdin;  fname = "<stdin>"; }
  93.                          else fp = fopen(fname,"rb");
  94.  
  95.     if (!fp) FatalError("file not found");
  96.  
  97.     /* find the size of the file */
  98.     fseek(fp, 0L, 2);
  99.     filesize = ftell(fp);
  100.     fseek(fp, 0L, 0);
  101.  
  102.     if (!(ptr = RawGIF = (byte *) malloc(filesize)))
  103.     FatalError("not enough memory to read gif file");
  104.  
  105.     if (!(Raster = (byte *) malloc(filesize)))
  106.     FatalError("not enough memory to read gif file");
  107.  
  108.     if (fread(ptr, filesize, 1, fp) != 1)
  109.     FatalError("GIF data read failed");
  110.  
  111.     if (strncmp(ptr, id, 6))
  112.     FatalError("not a GIF file");
  113.  
  114.     ptr += 6;
  115.  
  116. /* Get variables from the GIF screen descriptor */
  117.  
  118.     ch = NEXTBYTE;
  119.     RWidth = ch + 0x100 * NEXTBYTE;    /* screen dimensions... not used. */
  120.     ch = NEXTBYTE;
  121.     RHeight = ch + 0x100 * NEXTBYTE;
  122.  
  123.     if (Verbose)
  124.     fprintf(stderr, "screen dims: %dx%d.\n", RWidth, RHeight);
  125.  
  126.     ch = NEXTBYTE;
  127.     HasColormap = ((ch & COLORMAPMASK) ? True : False);
  128.  
  129.     BitsPerPixel = (ch & 7) + 1;
  130.     numcols = ColorMapSize = 1 << BitsPerPixel;
  131.     BitMask = ColorMapSize - 1;
  132.  
  133.     Background = NEXTBYTE;        /* background color... not used. */
  134.  
  135.     if (NEXTBYTE)        /* supposed to be NULL */
  136.     FatalError("corrupt GIF file (bad screen descriptor)");
  137.  
  138.  
  139. /* Read in global colormap. */
  140.  
  141.     if (HasColormap) {
  142.     if (Verbose)
  143.         fprintf(stderr, "%s is %dx%d, %d bits per pixel, (%d colors).\n",
  144.         fname, Width,Height,BitsPerPixel, ColorMapSize);
  145.     for (i = 0; i < ColorMapSize; i++) {
  146.         Red[i] = NEXTBYTE;
  147.         Green[i] = NEXTBYTE;
  148.         Blue[i] = NEXTBYTE;
  149.             used[i] = 0;
  150.         }
  151.         numused = 0;
  152.  
  153.         }
  154.  
  155.     else {  /* no colormap in GIF file */
  156.         fprintf(stderr,"warning!  no colortable in this file.  Winging it.\n");
  157.         if (!numcols) numcols=256;
  158.         for (i=0; i<numcols; i++) cols[i] = (unsigned long) i;
  159.         }
  160.  
  161. /* Check for image seperator */
  162.  
  163.     if (NEXTBYTE != IMAGESEP)
  164.     FatalError("corrupt GIF file (no image separator)");
  165.  
  166. /* Now read in values from the image descriptor */
  167.  
  168.     ch = NEXTBYTE;
  169.     LeftOfs = ch + 0x100 * NEXTBYTE;
  170.     ch = NEXTBYTE;
  171.     TopOfs = ch + 0x100 * NEXTBYTE;
  172.     ch = NEXTBYTE;
  173.     Width = ch + 0x100 * NEXTBYTE;
  174.     ch = NEXTBYTE;
  175.     Height = ch + 0x100 * NEXTBYTE;
  176.     Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
  177.  
  178.     if (Verbose)
  179.     fprintf(stderr, "Reading a %d by %d %sinterlaced image...",
  180.         Width, Height, (Interlace) ? "" : "non-");
  181.  
  182.     else 
  183.         fprintf(stderr, "%s is %dx%d, %d colors  ",
  184.        fname, Width,Height,ColorMapSize);
  185.     
  186.  
  187. /* Note that I ignore the possible existence of a local color map.
  188.  * I'm told there aren't many files around that use them, and the spec
  189.  * says it's defined for future use.  This could lead to an error
  190.  * reading some files. 
  191.  */
  192.  
  193. /* Start reading the raster data. First we get the intial code size
  194.  * and compute decompressor constant values, based on this code size.
  195.  */
  196.  
  197.     CodeSize = NEXTBYTE;
  198.     ClearCode = (1 << CodeSize);
  199.     EOFCode = ClearCode + 1;
  200.     FreeCode = FirstFree = ClearCode + 2;
  201.  
  202. /* The GIF spec has it that the code size is the code size used to
  203.  * compute the above values is the code size given in the file, but the
  204.  * code size used in compression/decompression is the code size given in
  205.  * the file plus one. (thus the ++).
  206.  */
  207.  
  208.     CodeSize++;
  209.     InitCodeSize = CodeSize;
  210.     MaxCode = (1 << CodeSize);
  211.     ReadMask = MaxCode - 1;
  212.  
  213. /* Read the raster data.  Here we just transpose it from the GIF array
  214.  * to the Raster array, turning it from a series of blocks into one long
  215.  * data stream, which makes life much easier for ReadCode().
  216.  */
  217.  
  218.     ptr1 = Raster;
  219.     do {
  220.     ch = ch1 = NEXTBYTE;
  221.     while (ch--) *ptr1++ = NEXTBYTE;
  222.     if ((Raster - ptr1) > filesize)
  223.         FatalError("corrupt GIF file (unblock)");
  224.     } while(ch1);
  225.  
  226.     free(RawGIF);        /* We're done with the raw data now... */
  227.  
  228.     if (Verbose) {
  229.     fprintf(stderr, "done.\n");
  230.     fprintf(stderr, "Decompressing...");
  231.     }
  232.  
  233.  
  234. /* Allocate the X Image */
  235.     Image = (byte *) malloc(Width*Height);
  236.     if (!Image) FatalError("not enough memory for XImage");
  237. /*
  238.     theImage = XCreateImage(theDisp,theVisual,8,ZPixmap,0,Image,
  239.                          Width,Height,8,Width);
  240.     if (!theImage) FatalError("unable to create XImage");
  241. */
  242.     BytesPerScanline = Width;
  243.  
  244.  
  245. /* Decompress the file, continuing until you see the GIF EOF code.
  246.  * One obvious enhancement is to add checking for corrupt files here.
  247.  */
  248.  
  249.     Code = ReadCode();
  250.     while (Code != EOFCode) {
  251.  
  252. /* Clear code sets everything back to its initial value, then reads the
  253.  * immediately subsequent code as uncompressed data.
  254.  */
  255.  
  256.     if (Code == ClearCode) {
  257.         CodeSize = InitCodeSize;
  258.         MaxCode = (1 << CodeSize);
  259.         ReadMask = MaxCode - 1;
  260.         FreeCode = FirstFree;
  261.         CurCode = OldCode = Code = ReadCode();
  262.         FinChar = CurCode & BitMask;
  263.         AddToPixel(FinChar);
  264.     }
  265.     else {
  266.  
  267. /* If not a clear code, then must be data: save same as CurCode and InCode */
  268.  
  269.         CurCode = InCode = Code;
  270.  
  271. /* If greater or equal to FreeCode, not in the hash table yet;
  272.  * repeat the last character decoded
  273.  */
  274.  
  275.         if (CurCode >= FreeCode) {
  276.         CurCode = OldCode;
  277.         OutCode[OutCount++] = FinChar;
  278.         }
  279.  
  280. /* Unless this code is raw data, pursue the chain pointed to by CurCode
  281.  * through the hash table to its end; each code in the chain puts its
  282.  * associated output code on the output queue.
  283.  */
  284.  
  285.         while (CurCode > BitMask) {
  286.         if (OutCount > 1024) {
  287.             fprintf(stderr,"\nCorrupt GIF file (OutCount)!\n");
  288.                     _exit(-1);  /* calling 'exit(-1)' dumps core, so I don't */
  289.                     }
  290.         OutCode[OutCount++] = Suffix[CurCode];
  291.         CurCode = Prefix[CurCode];
  292.         }
  293.  
  294. /* The last code in the chain is treated as raw data. */
  295.  
  296.         FinChar = CurCode & BitMask;
  297.         OutCode[OutCount++] = FinChar;
  298.  
  299. /* Now we put the data out to the Output routine.
  300.  * It's been stacked LIFO, so deal with it that way...
  301.  */
  302.  
  303.         for (i = OutCount - 1; i >= 0; i--)
  304.         AddToPixel(OutCode[i]);
  305.         OutCount = 0;
  306.  
  307. /* Build the hash table on-the-fly. No table is stored in the file. */
  308.  
  309.         Prefix[FreeCode] = OldCode;
  310.         Suffix[FreeCode] = FinChar;
  311.         OldCode = InCode;
  312.  
  313. /* Point to the next slot in the table.  If we exceed the current
  314.  * MaxCode value, increment the code size unless it's already 12.  If it
  315.  * is, do nothing: the next code decompressed better be CLEAR
  316.  */
  317.  
  318.         FreeCode++;
  319.         if (FreeCode >= MaxCode) {
  320.         if (CodeSize < 12) {
  321.             CodeSize++;
  322.             MaxCode *= 2;
  323.             ReadMask = (1 << CodeSize) - 1;
  324.         }
  325.         }
  326.     }
  327.     Code = ReadCode();
  328.     }
  329.  
  330.     free(Raster);
  331.  
  332.     if (Verbose)
  333.     fprintf(stderr, "done.\n");
  334.     else
  335.         fprintf(stderr,"(of which %d are used)\n",numused);
  336.  
  337.     if (fp != stdin)
  338.     fclose(fp);
  339. /*
  340.     ColorDicking(fname);
  341. */    
  342. }
  343.  
  344.  
  345. /* Fetch the next code from the raster data stream.  The codes can be
  346.  * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
  347.  * maintain our location in the Raster array as a BIT Offset.  We compute
  348.  * the byte Offset into the raster array by dividing this by 8, pick up
  349.  * three bytes, compute the bit Offset into our 24-bit chunk, shift to
  350.  * bring the desired code to the bottom, then mask it off and return it. 
  351.  */
  352. ReadCode()
  353. {
  354. int RawCode, ByteOffset;
  355.  
  356.     ByteOffset = BitOffset / 8;
  357.     RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
  358.     if (CodeSize >= 8)
  359.     RawCode += (0x10000 * Raster[ByteOffset + 2]);
  360.     RawCode >>= (BitOffset % 8);
  361.     BitOffset += CodeSize;
  362.     return(RawCode & ReadMask);
  363. }
  364.  
  365.  
  366. AddToPixel(Index)
  367. byte Index;
  368. {
  369.     if (YC<Height)
  370.         *(Image + YC * BytesPerScanline + XC) = Index;
  371.  
  372.     if (!used[Index]) { used[Index]=1;  numused++; }
  373.  
  374. /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
  375.  
  376.     if (++XC == Width) {
  377.  
  378. /* If a non-interlaced picture, just increment YC to the next scan line. 
  379.  * If it's interlaced, deal with the interlace as described in the GIF
  380.  * spec.  Put the decoded scan line out to the screen if we haven't gone
  381.  * past the bottom of it
  382.  */
  383.  
  384.     XC = 0;
  385.     if (!Interlace) YC++;
  386.     else {
  387.         switch (Pass) {
  388.         case 0:
  389.             YC += 8;
  390.             if (YC >= Height) {
  391.             Pass++;
  392.             YC = 4;
  393.             }
  394.         break;
  395.         case 1:
  396.             YC += 8;
  397.             if (YC >= Height) {
  398.             Pass++;
  399.             YC = 2;
  400.             }
  401.         break;
  402.         case 2:
  403.             YC += 4;
  404.             if (YC >= Height) {
  405.             Pass++;
  406.             YC = 1;
  407.             }
  408.         break;
  409.         case 3:
  410.             YC += 2;
  411.         break;
  412.         default:
  413.         break;
  414.         }
  415.     }
  416.     }
  417. }
  418.  
  419.  
  420. #ifdef    NOTDEF
  421. /*************************/
  422. ColorDicking(fname)
  423. char *fname;
  424. {
  425.     /* we've got the picture loaded, we know what colors are needed. get 'em */
  426.  
  427.     register int   i,j;
  428.     static byte    lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
  429.     byte           lmask, *ptr;
  430.  
  431.  
  432.     if (!HasColormap) return;
  433.     /* no need to allocate any colors if no colormap in GIF file */
  434.  
  435.     /* Allocate the X colors for this picture */
  436.  
  437.     if (nostrip)  {   /* nostrip was set.  try REAL hard to do it */
  438.         for (i=j=0; i<numcols; i++) {
  439.             if (used[i]) {
  440.                 defs[i].red   = Red[i]<<8;
  441.                 defs[i].green = Green[i]<<8;
  442.                 defs[i].blue  = Blue[i]<<8;
  443.                 defs[i].flags = DoRed | DoGreen | DoBlue;
  444.                 if (!XAllocColor(theDisp,theCmap,&defs[i])) { 
  445.                     j++;  defs[i].pixel = 0xffff;
  446.                     }
  447.                 cols[i] = defs[i].pixel;
  448.                 }
  449.             }
  450.  
  451.         if (j) {        /* failed to pull it off */
  452.             XColor ctab[256];
  453.             int    dc;
  454.  
  455.             dc = (dispcells<256) ? dispcells : 256;
  456.  
  457.             fprintf(stderr,"failed to allocate %d out of %d colors.  Trying extra hard.\n",j,numused);
  458.  
  459.             /* read in the color table */
  460.             for (i=0; i<dc; i++) ctab[i].pixel = i;
  461. /*
  462.             XQueryColors(theDisp,theCmap,ctab,dc);
  463. */
  464.             /* run through the used colors.  any used color that has a pixel
  465.                value of 0xffff wasn't allocated.  for such colors, run through
  466.                the entire X colormap and pick the closest color */
  467.  
  468.             for (i=0; i<numcols; i++)
  469.                 if (used[i] && cols[i]==0xffff) {  /* an unallocated pixel */
  470.                     int d, mdist, close;
  471.                     unsigned long r,g,b;
  472.  
  473.                     mdist = 100000;   close = -1;
  474.                     r =  Red[i];
  475.                     g =  Green[i];
  476.                     b =  Blue[i];
  477.                     for (j=0; j<dc; j++) {
  478.                         d = abs(r - (ctab[j].red>>8)) +
  479.                             abs(g - (ctab[j].green>>8)) +
  480.                             abs(b - (ctab[j].blue>>8));
  481.                         if (d<mdist) { mdist=d; close=j; }
  482.                         }
  483.                     if (close<0) FatalError("simply can't do it.  Sorry.");
  484.                     bcopy(&defs[close],&defs[i],sizeof(XColor));
  485.                     cols[i] = ctab[close].pixel;
  486.                     }
  487.             }    /* end 'failed to pull it off' */
  488.         }
  489.  
  490.     else {          /* strip wasn't set, do the best auto-strip */
  491.         j = 0;
  492.         while (strip<8) {
  493.             lmask = lmasks[strip];
  494.             for (i=0; i<numcols; i++)
  495.                 if (used[i]) {
  496.                     defs[i].red   = (Red[i]  &lmask)<<8;
  497.                     defs[i].green = (Green[i]&lmask)<<8;
  498.                     defs[i].blue  = (Blue[i] &lmask)<<8;
  499.                     defs[i].flags = DoRed | DoGreen | DoBlue;
  500.                     if (!XAllocColor(theDisp,theCmap,&defs[i])) break;
  501.                     cols[i] = defs[i].pixel;
  502.                     }
  503.  
  504.             if (i<numcols) {        /* failed */
  505.                 strip++;  j++;
  506.                 for (i--; i>=0; i--)
  507.                     if (used[i]) XFreeColors(theDisp,theCmap,cols+i,1,0L);
  508.                 }
  509.             else break;
  510.             }
  511.  
  512.         if (j && strip<8)
  513.             fprintf(stderr,"%s stripped %d bits\n"fname,strip);
  514.  
  515.         if (strip==8) {
  516.             fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n");
  517.             for (i=0; i<numcols; i++) cols[i]=i;
  518.             }
  519.         }
  520.  
  521.     ptr = Image;
  522.     for (i=0; i<Height; i++)
  523.         for (j=0; j<Width; j++,ptr++) 
  524.             *ptr = (byte) cols[*ptr];
  525. }
  526.  
  527. #endif
  528.